/* autosuggest: 自动完成组件 program by hgx 20091222 last modify 20091228 */
(function($){
	$.fn.autosuggest = function(config){
		var cfg = $.extend({url: '', optionTag: 'p', onchange: new Function()}, config || {});
		return this.each(function(){
			new _autosuggest(cfg, this);
		});
	};
	var _autosuggest = function(cfg, input){
		var _self = this;
		this.cfg = cfg;
		this.cache = $.extend({},{
			inx:   0,
			input: $(input),
			box:   null,
			mask:  null,
			query: '',
			result: ''
		});
		this.genLayout();
		this.bindInputEve();
		this.hide();
		$('html > body').click(function(){_self.hide();});
	};
	$.extend(_autosuggest.prototype, {
		genLayout: function(){
			var html = [
				'<iframe id="autoSuggestMask" frameborder="0" src="about:blank" scrolling="no" class="mask"></iframe>',
				'<div id="autoSuggestBox" class="autosuggest"></div>'
			];
			if($('#autoSuggestBox').length == 0){
				$('html>body').append(html.join(''));
			}
			this.cache.box  = $('#autoSuggestBox');
			this.cache.mask = $('#autoSuggestMask');
		},
		updateList: function(html){
			this.cache.box.find(this.cfg.optionTag).unbind();
			this.cache.box.html(html);
			this.bindOptEve();
			this.show();
		},
		show: function(){
			var box = this.cache.box, input = this.cache.input;
			if($.browser.msie && $.browser.version == '6.0')
			box.css('width', input.outerWidth() + 'px');
			box.add(this.cache.mask)
			.show()
			.css({
				left: input.offset().left - 1 + 'px',
				top: input.offset().top + input.outerHeight() + 'px',
				minWidth: input.outerWidth() + 'px'
			})
			.eq(1)
			.css({
				width: box.outerWidth() + 'px',
				height: box.outerHeight() + 'px',
				zIndex: box.css('zIndex') - 1
			});
		},
		hide: function(){
			this.cache.box.add(this.cache.mask).hide();
			this.cache.box.find(this.cfg.optionTag).removeClass('selected');
			this.cache.inx = 0;
		},
		bindOptEve: function(){
			var _self = this;
			var opts = $(this.cfg.optionTag, this.cache.box);
			opts.click(function(e){
				_self.hide();
				_self.inputVal(_self.cache.input, $(this).text());
				_self.cache.inx = opts.index(this);
			})
			.mouseover(function(e){
				opts.removeClass('selected');
				$(this).addClass('selected');
				_self.cache.inx = opts.index(this);
			});
		},
		navOptByKey: function(k){
			var inx = 0, preInx = this.cache.inx, opts = this.cache.box.find(this.cfg.optionTag), len = opts.length;
			if($.inArray(k, [13, 38, 40]) == -1) return;
			if(this.cache.box.css('display') == 'none') return;
			if(k == 38){
				inx = preInx - 1;
				if(inx < 0) inx = len - 1;
			}else if(k == 40){
				inx = preInx + 1;
				if(inx >= len) inx = 0;
			}else if(k == 13){
				this.inputVal(this.cache.input, opts.eq(preInx).text());
				this.hide();
				return;
			}
			opts.eq(preInx).removeClass('selected');
			opts.eq(inx).addClass('selected');
			this.inputVal(this.cache.input, opts.eq(inx).text());
			this.cache.inx = inx;
		},
		bindInputEve:function(){
			var _self = this, input = this.cache.input;
			input.keyup(function(e){
				if($.inArray(e.keyCode, [13, 38, 40]) >= 0) return;
				_self.req(_self.inputVal($(this)));
			})
			.keydown(function(e){
				_self.navOptByKey(e.keyCode);
			});
		},
		inputVal: function(input, val){
			var rVal = '';
			if(input[0].tagName.toLowerCase() == 'input'){
				rVal = input.val(val);
			}else if(input.attr('contentEditable') == 'true'){
				rVal = input.text(val);
			}else if($('[contentEditable="true"]', input).length > 0){
				rVal = $('[contentEditable="true"]', input).eq(0).text(val);
			}
			if(val && val != undefined && val != this.cache.box.find(this.cfg.optionTag).eq(this.cache.inx).text()){
				this.cfg.onchange.call(input, val);
			}
			return rVal;
		},
		
		req: function(d){
			var _self = this, reqType = this.cache.input.attr('id');
			if(!d || d == undefined || d == ''){
				this.hide();
				return;
			};
			var query = $.param({url: this.cfg.url, type: reqType, query: d});
			if(query == this.cache.query && $.trim(this.cache.result) != ''){
				this.show();
				return;
			}
			$.get(this.cfg.url, {type: encodeURIComponent(reqType), query: encodeURIComponent(d)}, function(html){
			  if($.trim(html) == ''){
				  _self.hide();
				}else{
				  _self.updateList(html);
				}
				_self.cache.query = query;
				_self.cache.result = html;
			});
		}	
	});
})(jQuery);